﻿using Danikor.FormManagement;
using Danikor.FormManagement.EntityFrameworkCore;
using Danikor.MessageManagement;
using Danikor.MessageManagement.EntityFrameworkCore;
using Danikor.SerialNumberManagement;
using Danikor.SerialNumberManagement.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.BackgroundJobs.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.OpenIddict.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement;
using Volo.Abp.TenantManagement.EntityFrameworkCore;

namespace MPS.EntityFrameworkCore;

[ReplaceDbContext(typeof(IIdentityDbContext))]
[ReplaceDbContext(typeof(ITenantManagementDbContext))]
[ReplaceDbContext(typeof(ISerialNumberManagementDbContext))]
[ReplaceDbContext(typeof(IFormManagementDbContext))]
[ReplaceDbContext(typeof(IMessageManagementDbContext))]
[ConnectionStringName("Default")]
public class MPSDbContext :
    AbpDbContext<MPSDbContext>,
    IIdentityDbContext,
    ITenantManagementDbContext,
    ISerialNumberManagementDbContext,
    IFormManagementDbContext,
    IMessageManagementDbContext
{
    /* Add DbSet properties for your Aggregate Roots / Entities here. */

    #region Entities from the modules

    /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext
     * and replaced them for this DbContext. This allows you to perform JOIN
     * queries for the entities of these modules over the repositories easily. You
     * typically don't need that for other modules. But, if you need, you can
     * implement the DbContext interface of the needed module and use ReplaceDbContext
     * attribute just like IIdentityDbContext and ITenantManagementDbContext.
     *
     * More info: Replacing a DbContext of a module ensures that the related module
     * uses this DbContext on runtime. Otherwise, it will use its own DbContext class.
     */

    //Identity
    public DbSet<IdentityUser> Users { get; set; }
    public DbSet<IdentityRole> Roles { get; set; }
    public DbSet<IdentityClaimType> ClaimTypes { get; set; }
    public DbSet<OrganizationUnit> OrganizationUnits { get; set; }
    public DbSet<IdentitySecurityLog> SecurityLogs { get; set; }
    public DbSet<IdentityLinkUser> LinkUsers { get; set; }
    public DbSet<IdentityUserDelegation> UserDelegations { get; set; }

    // Tenant Management
    public DbSet<Tenant> Tenants { get; set; }
    public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }


    #region 序列号管理模块
    public DbSet<SerialNumberDefinition> SerialNumberDefinitions => throw new System.NotImplementedException();

    public DbSet<RuleDefinition> RuleDefinitions => throw new System.NotImplementedException();

    public DbSet<SerialNumberConfiguration> SerialNumberConfigurations => throw new System.NotImplementedException();

    public DbSet<SerialNumberInstance> SerialNumberInstances => throw new System.NotImplementedException();

    public DbSet<RuleInstance> RuleInstances => throw new System.NotImplementedException();

    public DbSet<SerialNumberResetInstance> SerialNumberResetInstances => throw new System.NotImplementedException();

    #endregion

    #region 表单模块
    public DbSet<FormDefinition> FormDefinitions { get; set; }
    public DbSet<FormDefinitionConfiguration> FormDefinitionConfigurations { get; set; }
    public DbSet<FormDefinitionControl> FormDefinitionControls { get; set; }
    public DbSet<FormDefinitionActivity> FormDefinitionActivities { get; set; }
    public DbSet<FormInstance> FormInstances { get; set; }
    public DbSet<FormInstanceTransaction> FormInstanceTransactions { get; set; }
    public DbSet<FormFile> FormFiles { get; set; }
    public DbSet<FormAttachment> FormAttachments { get; set; }
    #endregion

    #region 枚举
    public DbSet<EnumDefinition> EnumDefinitions { get; set; }
    public DbSet<EnumDefinitionItem> EnumDefinitionItems { get; set; }
    #endregion

    #region 消息模块
    public DbSet<EventMessage> EventMessages { get; set; }
    public DbSet<MessageBox> MessageBoxes { get; set; }
    public DbSet<MessageMedia> MessageMedias { get; set; }
    public DbSet<MessageTemplate> MessageTemplates { get; set; }
    #endregion

    #endregion

    public MPSDbContext(DbContextOptions<MPSDbContext> options)
        : base(options)
    {

    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        /* Include modules to your migration db context */

        builder.ConfigurePermissionManagement();
        builder.ConfigureSettingManagement();
        builder.ConfigureBackgroundJobs();
        builder.ConfigureAuditLogging();
        builder.ConfigureIdentity();
        builder.ConfigureOpenIddict();
        builder.ConfigureFeatureManagement();
        builder.ConfigureTenantManagement();
        builder.ConfigureSerialNumberManagement(x => x.TablePrefix = MPSConsts.DanikorModuleTablePrefix);
        builder.ConfigureFormManagement(x => x.TablePrefix = MPSConsts.DanikorModuleTablePrefix);
        builder.ConfigureMessageManagement(x => x.TablePrefix = MPSConsts.DanikorModuleTablePrefix);

        /* Configure your own tables/entities inside here */

        //builder.Entity<YourEntity>(b =>
        //{
        //    b.ToTable(MPSConsts.DbTablePrefix + "YourEntities", MPSConsts.DbSchema);
        //    b.ConfigureByConvention(); //auto configure for the base class props
        //    //...
        //});
    }
}
